package com.test.demo.filter;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 重写 HttpServletRequestWrapper
 * 处理json报文请求,并向下传递
 *
 * @author zx
 * @Version 1.0
 */
public class MyHttpServletRequestWapper extends HttpServletRequestWrapper {

    private static final Logger log = LoggerFactory.getLogger(MyHttpServletRequestWapper.class);
    /***
     * 缓存的容器，当request.getInputStream()中有数据进行缓存
     */
    private byte[] body = null;

    /**
     * 存储请求数据
     *
     * @param request
     * @throws IllegalArgumentException if the request is null
     */
    public MyHttpServletRequestWapper(HttpServletRequest request) throws IOException {
        //让父类进行初始化
        super(request);
        //将数据拷贝进body中
        body = StreamUtils.copyToByteArray(request.getInputStream());
        //打个log,看下有没有数据
        log.info("body:{}", body.length);
        //一般只对get起作用
        log.info("QueryString:{}", this.getQueryString());
    }


    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }


    @Override
    public String getParameter(String name) {
        return super.getParameter(name);
    }


    @Override
    public Map<String, String[]> getParameterMap() {
        //判断是否是application/json上传
        if (body.length > 0 && getContentType() != null && getContentType().contains("application/json")) {
            //获取json数据
            StringBuffer json = new StringBuffer();
            String line = null;
            try {
                BufferedReader reader = getReader();
                while ((line = reader.readLine()) != null) {
                    json.append(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            Map<String, String[]> map = new HashMap<>();
            if (!StringUtils.isEmpty(json)) {
                //使用JSON工具将其转换成map
                try {
                    map = JSON.parseObject(json.toString(), Map.class);
                    log.info("入参为： {}", map);
                } catch (JSONException e) {
                    List<String> strings = JSON.parseArray(json.toString(), String.class);
                    String[] sArr = strings != null ? strings.toArray(new String[strings.size()]) : new String[1];
                    map.put("param", sArr);
                    StringBuffer sb = new StringBuffer();
                    for(int i = 0; i < sArr.length; i++){
                        sb. append(sArr[i]);
                    }
                    log.info("入参为： {}", sb.toString());
                }
            }

            return map;
        }
        //不是application/json上传,直接使用原来提供的相关方法就好
        Map<String, String[]> parameterMap = super.getParameterMap();
        log.info("使用的是原生的requestMap:{}", parameterMap);
        return parameterMap;
    }


    public Map<String, String> getMap(Map<String, String[]> map) {
        Map<String, String> paramterMap = new HashMap<>();
        //遍历数组
        for (String key : map.keySet()) {
            //将值key，key对应的的value 赋值到map参数中
            Object obj = null;
            try {
                //post请求需要使用此方式获取参数字符串
                obj = (Object) map.get(key)[0];
            } catch (ClassCastException e) {
                //get获取
                obj = (Object) map.get(key);
            }
            paramterMap.put(key, obj + "");
        }
        return paramterMap;
    }


    /**
     * 重写方法，将缓存的数据body转换成ServletInputStream返回
     *
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }
        };
    }


}
